package org.fujene.diskblock.blockwise;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.UnsupportedEncodingException;

import org.fujene.diskblock.DiskBlock;
import org.fujene.memoryblock.MemoryBlock;
import org.fujene.memoryblock.blockwise.BlockwiseDictionaryBlock;
import org.fujene.structure.Constants;
import org.fujene.structure.ExtendTerm;
import org.fujene.structure.LookupPointer;
import org.fujene.toolbox.ByteConverter;

/**
 * DictionaryBlockのサブセットとして機能します。
 */
public class BlockwiseDictionaryDiskBlock extends DiskBlock {

	public BlockwiseDictionaryDiskBlock(File fileDesc) throws Exception {
		super(fileDesc);
	}
	
	public BlockwiseDictionaryDiskBlock(MemoryBlock memBlock, String dir) {
		super(memBlock, dir);
	}

	// 1単語分の辞書
	private class Dictionary {
		LookupPointer nextPtr;
		int docFreq;
		LookupPointer[] invIndices;
		int strlen;
		String str;

		// 読み込み用
		public Dictionary(int from, boolean readStr) throws Exception {
			this.nextPtr = ByteConverter.getPtr(getBody(from, PTR));
			if(this.nextPtr.equals(Constants.emptyPointer))
				this.nextPtr = null;
			from += PTR;

			this.docFreq = ByteConverter.byteToInt(getBody(from, DOCFREQ));
			from += DOCFREQ;

			invIndices = new LookupPointer[getOption(1)];
			for (int i = 0; i < this.invIndices.length; i++) {
				this.invIndices[i] = ByteConverter.getPtr(getBody(from, PTR));
				if(this.invIndices.equals(Constants.emptyPointer))
					this.invIndices[i] = null;
				from += PTR;
			}

			if (readStr) {
				this.strlen = ByteConverter.byteToInt(getBody(from, STRLEN));
				from += STRLEN;

				try {
					this.str = new String(getBody(from, strlen), "UTF-8");
				} catch (UnsupportedEncodingException e) {
				}
			}
		}
	}

	public LookupPointer getNextPointer(int ptr) throws Exception {
		Dictionary ptredDic = new Dictionary(ptr, false);

		return ptredDic.nextPtr;
	}

	public LookupPointer getDocIDPointer(int ptr, int index) throws Exception {
		Dictionary ptredDic = new Dictionary(ptr, false);

		return ptredDic.invIndices[index];
	}

	// 情報読み込み
	public ExtendTerm getTerm(int ptr) throws Exception {
		Dictionary dict = new Dictionary(ptr, true);

		return new ExtendTerm(dict.str, dict.nextPtr, null, new LookupPointer(
				this.getID(), ptr), -1, dict.invIndices, null, dict.docFreq);
	}
	
	public int getTermCount() throws Exception{
		return this.getOption(0);
	}
		
	@Override
	public void readToMemory(MemoryBlock memBlock) {
		if(memBlock instanceof BlockwiseDictionaryBlock){
			try {
				memBlock.setOption(0, this.getOption(0));
				memBlock.setOption(1, this.getOption(1));
				memBlock.setBody(this.getBody(0, this.bodySize), 0);
				memBlock.setBodyVacancy(this.bodyVacancy);
			} catch (Exception e) {
			}
		}
	}

	@Override
	public byte[] getData() throws Exception {
		ByteArrayOutputStream stream = new ByteArrayOutputStream(this.bodySize + 4);
		
		stream.write(ByteConverter.intToByte(this.getOption(0), 4));
		stream.write(ByteConverter.intToByte(this.getOption(1), 4));
		stream.write(this.getBody(0, this.bodySize));
		
		return stream.toByteArray();
	}
}
